package phr;

import org.jdom.input.SAXBuilder;
import org.jdom.Document;
import org.jdom.JDOMException;
import org.jdom.Element;
import org.jdom.output.XMLOutputter;
import org.jdom.output.Format;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.List;

public class AccessControlList {
	Document ACList = null;
	
	
	public AccessControlList () {
		SAXBuilder builder = new SAXBuilder();
		try {
			ACList = builder.build(new ByteArrayInputStream("<root></root>".getBytes()));
		}
		catch (JDOMException e) {
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	public AccessControlList (String xml) {
		SAXBuilder builder = new SAXBuilder();
		try {
			ACList =
				builder.build(new ByteArrayInputStream(xml.getBytes()));
		} catch (JDOMException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	public String hasAccess(Identity identity) {
		List<Element> authorizedUserList = ACList.getRootElement().getChildren("user");
		String right = "denied";
		for (int index = 0; index < authorizedUserList.size(); index++) {
			Element user = (Element) authorizedUserList.get(index);
			if (user.getAttributeValue("id").equals(identity.id)) right = rightMeasure(user.getAttributeValue("right"), right);
		}
		List<Element> attributeRuleList = ACList.getRootElement().getChildren("rule");
		for (int index = 0; index < attributeRuleList.size(); index++) {
			Element rule = (Element) attributeRuleList.get(index);
			if (rule.getAttributeValue("role").equals(identity.role) || rule.getAttributeValue("role").equals("any")) {
				if (rule.getAttributeValue("department").equals(identity.department) || rule.getAttributeValue("department").equals("any")) {
					if (rule.getAttributeValue("organization").equals(identity.organization) || rule.getAttributeValue("organization").equals("any")) {
						right = rightMeasure(rule.getAttributeValue("right"), right);
					}
				}
			}
		}
		return right;
	}
	
	private String rightMeasure(String a, String b) {
		if (a.equals("own") || b.equals("own")) return "own";
		else if (a.equals("write") || b.endsWith("write")) return "write";
		else return "read";
	}
	
	public void authorizeUser(String id, String right) {
		List<Element> authorizedUserList = ACList.getRootElement().getChildren("user");
		authorizedUserList.add(new Element("user").setAttribute("id", id).setAttribute("right", right));		
	}
	
	public void authorizeRule(String role, String department, String organization, String right) {
		List<Element> attributeRuleList = ACList.getRootElement().getChildren("rule");
		attributeRuleList.add(new Element("rule")
												.setAttribute("role", role)
												.setAttribute("department", department)
												.setAttribute("organization", organization)
												.setAttribute("right", right));
	}
	
	public boolean revokeUser(String id) {
		List<Element> authorizedUserList = ACList.getRootElement().getChildren("user");
		for (int index = 0; index < authorizedUserList.size(); index++) {
			Element user = (Element) authorizedUserList.get(index);
			if (user.getAttributeValue("id").equals(id) && !user.getAttributeValue("rule").equals("own")) {
				authorizedUserList.remove(index);
				return true;
			}
		}
		return false;		
	}
	
	public boolean revokeUser(int index) {
		List<Element> authorizedUserList = ACList.getRootElement().getChildren("user");
		if (index < authorizedUserList.size() && index >= 0) {
			authorizedUserList.remove(index);
			return true;
		}
		return false;		
	}
	
	public boolean revokeRule(int index) {
		List<Element> attributeRuleList = ACList.getRootElement().getChildren("rule");
		if (index < attributeRuleList.size() && index >= 0) {
			attributeRuleList.remove(index);
			return true;
		}
		return false;
	}
	
	public List<Element> getList(String name) {
		List<Element> list = ACList.getRootElement().getChildren("name");
		return list;
	}
	
	public String getXMLString() {
		String xml;
		XMLOutputter outputter = new XMLOutputter(Format.getRawFormat());
		xml = outputter.outputString(ACList).replaceAll("[\n\r]", "");;
		return xml;
	}
	
	public void printACL() {
		System.out.println("-Authorized users-");
		printUsers();
		System.out.println("\n-Authorization rules-");
		printRules();
		System.out.println();
	}
	
	public void printUsers() {
		List<Element> list = ACList.getRootElement().getChildren("user");
		for (int index = 0; index < list.size(); index++) {
			Element e = list.get(index);
			System.out.println(" " + index + ". id = " + e.getAttributeValue("id") + " right = " + e.getAttributeValue("right"));
		}
	}
	
	public void printRules() {
		List<Element> list = ACList.getRootElement().getChildren("rule");
		if (list.size() == 0) System.out.println(" no rules");
		for (int index = 0; index < list.size(); index++) {
			Element e = list.get(index);
			System.out.println(" " + index + ". role = " + e.getAttributeValue("role") + " department = " + e.getAttributeValue("department") + " organization = " + e.getAttributeValue("organization") + " right = " + e.getAttributeValue("right"));
		}		
	}
}